/// Time in seconds.
///
/// # Example
///
/// ```
/// let second = Second::new(42);
/// assert_eq!(42, second.value());
/// ```
///
/// # Example
///
/// ```
/// let second = Second::default();
/// assert_eq!(0, second.value());
/// ```
pub struct Second {
    value: u64,
}

impl Second {
    // Constructs a new instance of [`Second`].
    // Note this is an associated function - no self.
    pub fn new(value: u64) -> Self {
        Self { value }
    }

    /// Returns the value in seconds.
    pub fn value(&self) -> u64 {
        self.value
    }
}

// Note: It is common and expected for types to implement both `Default`` and an
// empty `new` constructor. `new` is the constructor convention in Rust, and
// users expect it to exist, so if it is reasonable for the basic constructor to
// take no arguments, then it should, even if it is functionally identical to
// default.
//
// Hint: The advantage of implementing or deriving Default is that your type can
// now be used where a Default implementation is required, most prominently, any
// of the *or_default functions in the standard library.
#[allow(clippy::derivable_impls)]
impl Default for Second {
    fn default() -> Self {
        Self { value: 0 }
    }
}

fn main() {
    {
        let second = Second::new(42);
        println!("{}", second.value());
    }

    println!();

    {
        let second = Second::default();
        println!("{}", second.value());
    }
}
